// poj1325
// 题意：有两台机器A, B，分别有n和m个模块(<100)，初始两个机器都在0模块，
//       现在有k(<=1000)个任务，任务可以放在A机器的x模块或者B机器的y模块
//       上运行。机器切换模块需要一个费用。现在让你安排任务顺序以及放置
//       的机器，使得种的切换费用最小。
//
// 题解：每个任务要么放A要么放B，那么我们可以把A机器n个模块和B机器m个模块
//       分别建立两部点集，每个任务就是一条边连接两个点集（跳过可以放
//       0模块，因为初始不用切换）。现在相当于要求该图的最小点覆盖。
//       即没条边的端点至少有一个要属于这个最小点覆盖集合。
//       根据König定理，二分图的最小点覆盖数等于最大匹配数。
//
//       http://www.matrix67.com/blog/archives/116 
//
// run: $exec < input
// std: c++03
#include <iostream>
#include <vector>

namespace biartite_graph
{
	int const maxn = 5008;
	typedef std::vector<int> edge_type;
	typedef std::vector<int>::iterator edge_iter;
	typedef std::vector<edge_type> graph_type;

	graph_type graph;
	edge_type linked;
	bool vis[maxn];
	int n, half;

	void init(int tn, int thalf)
	{
		n = tn; half = thalf;
		graph.clear();
		graph.resize(n);
		linked.clear();
		linked.resize(n);
		std::fill(vis, vis + n, false);
	}

	void add_edge(int u, int v)
	{
		graph[u].push_back(v); graph[v].push_back(u);
	}

	bool hungarian_dfs(int u)
	{
		for (edge_iter it = graph[u].begin(); it != graph[u].end(); ++it) {
			int v = *it;
			if (vis[v]) continue;
			vis[v] = true;
			if (linked[v] == -1 || hungarian_dfs(linked[v])) {
				linked[u] = v;
				linked[v] = u;
				return true;
			}
		}
		return false;
	}

	int max_match()
	{
		std::fill(linked.begin(), linked.end(), -1);
		int ret = 0;
		for (int i = 0; i < half; i++) {
			std::fill(vis, vis + n, false);
			if (hungarian_dfs(i)) ret++;
		}
		return ret;
	}
};

int main()
{
	std::ios::sync_with_stdio(false);
	for (int n, m, k; std::cin >> n >> m >> k && n; ) {
		biartite_graph::init(n + m, n);
		for (int i = 0, t, x, y; i < k; i++) {
			std::cin >> t >> x >> y;
			if (!x || !y) continue;
			biartite_graph::add_edge(x, n + y);
		}
		std::cout << biartite_graph::max_match() << '\n';
	}
}

